A platform is a combination of hardware architecture and/or software that enables software to run on user devices, such as desktop computers, mobile phones, and tablets. Software platforms are typically a combination of software libraries and other executables that present well-defined Application Programming Interfaces (“API”). Software developers are increasingly utilizing modern software platforms to enable the creation of platform-independent applications. Modern software platforms typically include a programming language, the compiled output of which executes within the context of machine-dependent programs, known as virtual machines (“VM”).
Java is a registered trademark of Oracle Corporation. Oracle associates the Java trademark with its eponymous computer programming language, Java Virtual Machine (“JVM,”) and related infrastructure and tools. .NET is a registered trademark of Microsoft Corporation. For its .NET framework, Microsoft provides its C# programming language, .NET Common Language Runtime, and related infrastructure and tools. The .NET Common Language Runtime is the Virtual Machine component of Microsoft's NET framework.
A VM is a software program or library that permits an isolated processing environment to exist on a computer system. VMs hide or abstract the details of the underlying computer system from the software that executes within each VM. To create platform-independent applications, software developers use platform tools to compile the programming language source code into the software executable that runs on the VMs, also known as bytecode. Bytecode is typically a set of binary files that include platform-neutral instructions for implementing application behavior. The VMs interpret the bytecode, and execute corresponding native instructions on the target computer system associated with the bytecode. Examples of software platforms that enable the creation of computer system-independent applications include the Java and .NET platforms.
The Java programming language and runtime package support the tenets of object-oriented programming, which includes the principles of inheritance, polymorphism, and data hiding. Java organizes programming objects into conceptual classes, and saves the compiled bytecode for its classes into data files, also known as class files. Typically, the Java compiler generates one class file for each class defined in a source file, and the name of the class file corresponds to the defined class name within the source file.
In the case of the Java programming language, the Java compiler converts the source code for each Java class definition into its associated bytecode. For example, the Java compiler accepts a source file named “MyClass.java” with source code that includes the class definition for named class “MyClass,” converts the source code to bytecode, and stores the bytecode in class file “MyClass.class”.
However, instead of defining all classes in separate files, software developers can also define one or more classes within another class. The outer class that includes the definitions of other classes is referred to as the enclosing class, and the classes defined within the enclosing class are referred to as nested, or inner classes.
Developers typically define inner classes to limit the scope of their behaviors to be within the same enclosing class and to ensure high cohesion between classes which share a well-defined responsibility. In Java, there are 4 types of inner classes: static member classes, member classes, local classes and anonymous classes.
When a member of a class is declared as ‘static’ in Java, by prefacing the member with the ‘static’ keyword, only one copy of the data is maintained for all objects of that class. Of the 4 types of inner classes, member classes and static member classes refer to classes that are declared within the body of an enclosing class, and are therefore named members of the enclosing class. Static member classes and member classes exhibit similar naming conventions and are therefore referred to as member classes henceforth.
Local classes and anonymous classes are classes that are defined within a method of an enclosing class, and therefore have scope that is local only to the method in which they are defined. Local classes have a defined name, and anonymous classes have no name. As a result, local and anonymous classes are often referred to as named non-member classes and unnamed non-member classes, respectively. Multiple, same-named local classes can be declared within the same outer class as long as the scope of the local classes differs.
In contrast to member classes, local classes and anonymous classes share a common naming scheme that includes synthetically-generated parts such as variables in their class names. The java compiler includes the synthetically-generated parts in the class names so that their class names are unique. This allows the proper bytecode for each local and anonymous class to be linked and executed at run time.
In general, classes having synthetically generated names are defined as any class name identified at run time that differs from its originally defined class name in source code, if such source code exists. With respect to Java, synthetically generated names are associated with class names for local classes, anonymous classes, generated classes, and lambda classes, in examples. Lambda classes are also known as lambda expressions. An example of a generated class is a bridge method. As a convenient shorthand, classes having synthetically generated names are also referred to as name synthesized classes.
Of the inner classes, only member classes are “fully named,” meaning that their original class names are not modified. Although member classes are defined within an enclosing class, the compiler generates a separate class file for each member class that includes the bytecode for each member class. The name for each member class file is the name of the member class appended to the enclosing class name. Using Java as an example, source file “Outer.java” provides a definition for class “Outer.” The class definition for class Outer then includes a class definition for a member class named “Inside.” The Java compiler generates class files “Outer.class” and “Outer$Inside.class,” which include the bytecode associated with the definitions of classes Outer and Inside, respectively.
Anonymous classes, in contrast, enable developers to declare and instantiate a class at the same time. Though they are classes, they do not have a class name in their source files. Anonymous classes allow developers to declare an inner class within the source code of an enclosing class without naming the class. Anonymous classes are typically utilized when developers need to construct only one locally-scoped instance of a class in an application.
Unlike local and member classes, an anonymous class definition is an expression. The expression associated with an anonymous class includes the “new” operator, and is therefore similar to a constructor call. Because an anonymous class definition is an expression, it is terminated with a semicolon. An anonymous class is a subclass of a named class or declared interface, where the anonymous class overrides some or the entire set of behaviors of the named superclass or interface.
As with member classes, the compiler generates individual class files that include the bytecode for each anonymous class. However, because anonymous classes have no name, the compiler synthetically generates a class file name for each anonymous class. Specifically, when naming each anonymous class, the Java compiler typically creates a name that includes the declared name of the enclosing class as a prefix, followed by a ‘$’ character, and followed by a generated numerical value suffix.
During compilation, the compiler performs “top-down” traversal of the source code for each enclosing class. For each anonymous class that the compiler encounters during compilation, the compiler monotonically increases the generated numerical value. A compiler performing compilation upon an enclosing class named “Enclosing,” for example, would typically generate class file name “Enclosing$1.class” for the first anonymous class encountered within class Enclosing, “Enclosing$2.class” for the second anonymous class encountered, etc. This provides each anonymous class with a uniquely named class file.
Though local classes are named classes like member classes, local classes can include synthetic parts in the compiled class file name. For example, when two same-named local classes are declared within the same enclosing class, but with different scope (e.g. within two different methods), the Java compiler typically creates a name that includes the declared name of the enclosing class as a prefix, followed by a ‘$’ character, followed by a generated numerical value and followed by the specifically declared local class name.
Software developers change the behavior of an application by making changes to the classes that define the behavior of the application. Java provides a limited ability to change the behavior of running applications without having to stop and restart the applications. This is accomplished via run-time class reloading. Run-time class reloading provides the ability to update the definitions of currently loaded classes of an application running on a computer system with redefined versions of the classes, in response to a dynamic class update to the existing classes.
The currently loaded classes are associated with versions of the classes that were loaded by a class loader of a JVM during creation of the application. For this reason, the class files that are currently loaded in a running instance of an application are also known as existing classes. Because the dynamic class update loads redefined versions of the existing classes at run-time, the redefined versions of the classes are also known as reloaded classes.
Java supports run-time class reloading via its HotSwap feature. Current HotSwap implementations are built into stock versions of major JVMs. Using HotSwap, a developer can create a new definition for a class currently loaded in a running instance of an application, and apply this new definition of the class without having to stop and restart the application instance to incorporate the new class definition. The new class definition is also known as a class redefinition.
However, HotSwap's run-time class redefinition capability is limited. It does not support many different ways that classes can be redefined. Specifically, HotSwap only supports redefinitions of method bodies of existing classes. In examples, HotSwap does not support changes to constructors of existing classes and changes to the superclass hierarchy of existing classes. In addition, HotSwap often experiences run-time execution errors when existing classes include inner classes such as anonymous classes, and the reloaded classes include changes that modify the contents or execution order of the anonymous classes.
The HotSpot VM has provided a limited ability to redefine classes at runtime since JDK 1.4. This functionality is largely based on the work of Mikhail Dmitriev, from “Safe Class and Data Evolution in Large and Long-Lived Java Applications,” PhD thesis, University of Glasgow, 2001. More recent run-time class redefinition proposals include “Dynamic code evolution for Java,” Thomas Würthinger, Proceedings of the 8th International Conference on the Principles and Practice of Programming in Java, PPPJ 2010, Vienna, Austria, Sep. 15-17, 2010. The Dynamic Code Evolution VM (DCEVM) allows arbitrary changes to class definitions. In addition, a publication by Allan Raundahl Gregersen, “Extending NetBeans with Dynamic Update of Active Modules,” PhD thesis, University of Southern Denmark, 2010, discusses dynamic update of code modules using the NetBeans development platform. NetBeans is a registered trademark of Oracle, Inc.
Currently, the most widespread run-time class reloading system in use is JRebel, an application-level system that enables runtime reloading of classes by utilizing bytecode re-writing at class load time. JRebel is a registered trademark of ZeroTurnaround USA, Inc.
For run-time reloading of member classes, though the contents of an originally-loaded class and a redefined class may change, a Java class loader always loads the correct class file from the list of class files in an application. This is because for member classes, the class file name created by the compiler is eponymous with its declared class name in the Java source code.
Fingerprint algorithms are primarily used to generate unique, fixed-length output data that acts as a shortened reference to the original data. This is useful when the original data is too cumbersome to use in its original format. The fixed-length output data, also referred to as a fingerprint, is a unique identifier that provides for such capabilities as searching and matching of the original data that would have been difficult or impossible using the format of the original data. A typical example of a fingerprint algorithm is a hash function.